package controller

import (
	"encoding/json"
	"net/http"

	"github.com/beego/beego/v2/server/web"
	"scase.io/application-auto-scaling-service/pkg/api/errors"
	"scase.io/application-auto-scaling-service/pkg/api/model"
	"scase.io/application-auto-scaling-service/pkg/api/response"
	"scase.io/application-auto-scaling-service/pkg/api/validator"
	"scase.io/application-auto-scaling-service/pkg/common"
	service "scase.io/application-auto-scaling-service/pkg/service/event"
	"scase.io/application-auto-scaling-service/pkg/utils/logger"
)

type EventController struct {
	web.Controller
}

const (
	urlParamEventId         = ":event_id"
	urlParamTopicUrn        = ":topic_urn"
	urlParamSubscriptionUrn = ":subscription_urn"
)

// 上报事件
func (c *EventController) Create() {
	tLogger := logger.GetTraceLogger(c.Ctx).WithField(logger.Stage, "create event")
	projectId := c.GetString(urlParamProjectId)
	req := model.CreateEventRequest{}
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
		response.Error(c.Ctx, http.StatusBadRequest, errors.NewErrorResp(errors.RequestParseError))
		tLogger.Error("Read create event req body err: %+v", err)
		return
	}
	if err := validator.Validate(&req); err != nil {
		response.Error(c.Ctx, http.StatusBadRequest,
			errors.NewErrorRespWithMessage(errors.RequestParamsError, err.Error()))
		tLogger.Error("The request parameter is err: %+v", err)
		return
	}
	s, err := service.NewEventService(projectId, c.Ctx, tLogger)
	if err != nil {
		response.Error(c.Ctx, http.StatusInternalServerError, errors.NewErrorResp(errors.AgencyClientError))
		tLogger.Error("new event service when create event err: %+v", err)
		return
	}
	resp, errC := s.CreateEvent(&req)
	if errC != nil {
		tLogger.Error("create event error:%+v", errC)
		response.Error(c.Ctx, http.StatusInternalServerError, errC.ErrMsg)
		return
	}
	response.Success(c.Ctx, http.StatusOK, resp)
}

// 获取事件列表
func (c *EventController) List() {
	tLogger := logger.GetTraceLogger(c.Ctx).WithField(logger.Stage, "list event")
	projectId := c.GetString(urlParamProjectId)
	s, err := service.NewEventService(projectId, c.Ctx, tLogger)
	if err != nil {
		response.Error(c.Ctx, http.StatusInternalServerError, errors.NewErrorResp(errors.AgencyClientError))
		tLogger.Error("new event service when list event err: %+v", err)
		return
	}
	queryParam := &model.QueryEventsParam{
		TraceId:      s.Ctx.Input.Query(service.FieldTraceId),
		ResourceType: s.Ctx.Input.Query(service.FieldResourceType),
		TraceState:   s.Ctx.Input.Query(service.FieldTraceState),
		StartTime:    s.Ctx.Input.Query(service.FieldStartTime),
		EndTime:      s.Ctx.Input.Query(service.FieldEndTime),
		EventType:    s.Ctx.Input.Query(service.FieldEventType),
	}
	if err := validator.Validate(queryParam); err != nil {
		response.Error(c.Ctx, http.StatusBadRequest,
			errors.NewErrorRespWithMessage(errors.RequestParamsError, err.Error()))
		tLogger.Error("The query parameter is err: %+v", err)
		return
	}
	resp, errC := s.ListEvents(queryParam, common.GetOffset(s.Ctx, tLogger), common.GetLimit(c.Ctx, tLogger))
	if errC != nil {
		tLogger.Error("list event error:%+v", errC)
		response.Error(c.Ctx, http.StatusInternalServerError, errC.ErrMsg)
		return
	}
	response.Success(c.Ctx, http.StatusOK, resp)
}

// 查询事件详情
func (c *EventController) Show() {
	tLogger := logger.GetTraceLogger(c.Ctx).WithField(logger.Stage, "show event")
	projectId := c.GetString(urlParamProjectId)
	s, err := service.NewEventService(projectId, c.Ctx, tLogger)
	if err != nil {
		response.Error(c.Ctx, http.StatusInternalServerError, errors.NewErrorResp(errors.AgencyClientError))
		tLogger.Error("new event service when show event err: %+v", err)
		return
	}
	eventId := c.GetString(urlParamEventId)
	resp, errC := s.ShowEvent(eventId)
	if errC != nil {
		tLogger.Error("show event error:%+v", errC)
		response.Error(c.Ctx, http.StatusInternalServerError, errC.ErrMsg)
		return
	}
	response.Success(c.Ctx, http.StatusOK, resp)
}

// 删除事件
func (c *EventController) Delete() {
	tLogger := logger.GetTraceLogger(c.Ctx).WithField(logger.Stage, "delete event")
	projectId := c.GetString(urlParamProjectId)
	s, err := service.NewEventService(projectId, c.Ctx, tLogger)
	if err != nil {
		response.Error(c.Ctx, http.StatusInternalServerError, errors.NewErrorResp(errors.AgencyClientError))
		tLogger.Error("new event service when delete event err: %+v", err)
		return
	}
	eventId := c.GetString(urlParamEventId)
	errC := s.DeleteEvent(eventId)
	if errC != nil {
		tLogger.Error("delete event error:%+v", errC)
		response.Error(c.Ctx, http.StatusInternalServerError, errC.ErrMsg)
		return
	}
	response.Success(c.Ctx, http.StatusNoContent, nil)
}

// 创建主题
func (c *EventController) CreateTopic() {
	tLogger := logger.GetTraceLogger(c.Ctx).WithField(logger.Stage, "create topic")
	projectId := c.GetString(urlParamProjectId)
	s, err := service.NewEventService(projectId, c.Ctx, tLogger)
	if err != nil {
		response.Error(c.Ctx, http.StatusInternalServerError, errors.NewErrorResp(errors.AgencyClientError))
		tLogger.Error("new event service when create topic err: %+v", err)
		return
	}
	req := &model.CreateTopicRequest{}
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, req); err != nil {
		response.Error(c.Ctx, http.StatusBadRequest, errors.NewErrorResp(errors.RequestParseError))
		tLogger.Error("Read create topic req body err: %+v", err)
		return
	}
	if err := validator.Validate(req); err != nil {
		response.Error(c.Ctx, http.StatusBadRequest,
			errors.NewErrorRespWithMessage(errors.RequestParamsError, err.Error()))
		tLogger.Error("The request parameter is err: %+v", err)
		return
	}
	resp, errC := s.CreateTopic(req)
	if errC != nil {
		tLogger.Error("create topic error:%+v", errC)
		response.Error(c.Ctx, http.StatusInternalServerError, errC.ErrMsg)
		return
	}
	response.Success(c.Ctx, http.StatusOK, resp)
}

// 删除主题
func (c *EventController) DeleteTopic() {
	tLogger := logger.GetTraceLogger(c.Ctx).WithField(logger.Stage, "delete topic")
	projectId := c.GetString(urlParamProjectId)
	s, err := service.NewEventService(projectId, c.Ctx, tLogger)
	if err != nil {
		response.Error(c.Ctx, http.StatusInternalServerError, errors.NewErrorResp(errors.AgencyClientError))
		tLogger.Error("new event service err when delete topic: %+v", err)
		return
	}
	errC := s.DeleteTopic()
	if errC != nil {
		tLogger.Error("delete topic error:%+v", errC)
		response.Error(c.Ctx, http.StatusInternalServerError, errC.ErrMsg)
		return
	}
	response.Success(c.Ctx, http.StatusNoContent, nil)
}

// 查询主题
func (c *EventController) ShowTopic() {
	tLogger := logger.GetTraceLogger(c.Ctx).WithField(logger.Stage, "show topic")
	projectId := c.GetString(urlParamProjectId)
	s, err := service.NewEventService(projectId, c.Ctx, tLogger)
	if err != nil {
		response.Error(c.Ctx, http.StatusInternalServerError, errors.NewErrorResp(errors.AgencyClientError))
		tLogger.Error("new event service when show topic err : %+v", err)
		return
	}
	resp, errC := s.ShowTopic()
	if errC != nil {
		tLogger.Error("show topic error:%+v", errC)
		response.Error(c.Ctx, http.StatusInternalServerError, errC.ErrMsg)
		return
	}
	response.Success(c.Ctx, http.StatusOK, resp)
}

// 查询主题
func (c *EventController) UpdateTopic() {
	tLogger := logger.GetTraceLogger(c.Ctx).WithField(logger.Stage, "update topic")
	projectId := c.GetString(urlParamProjectId)
	req := &model.UpdateTopicRequest{}
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, req); err != nil {
		response.Error(c.Ctx, http.StatusBadRequest, errors.NewErrorResp(errors.RequestParseError))
		tLogger.Error("Read update topic req body err: %+v", err)
		return
	}
	if err := validator.Validate(req); err != nil {
		response.Error(c.Ctx, http.StatusBadRequest,
			errors.NewErrorRespWithMessage(errors.RequestParamsError, err.Error()))
		tLogger.Error("The request parameter is err: %+v", err)
		return
	}
	s, err := service.NewEventService(projectId, c.Ctx, tLogger)
	if err != nil {
		response.Error(c.Ctx, http.StatusInternalServerError, errors.NewErrorResp(errors.AgencyClientError))
		tLogger.Error("new event service when update topic err : %+v", err)
		return
	}
	errC := s.UpdateTopic(req)
	if errC != nil {
		tLogger.Error("show topic error:%+v", errC)
		response.Error(c.Ctx, http.StatusInternalServerError, errC.ErrMsg)
		return
	}
	response.Success(c.Ctx, http.StatusAccepted, nil)
}

// 添加订阅
func (c *EventController) AddSubscription() {
	tLogger := logger.GetTraceLogger(c.Ctx).WithField(logger.Stage, "add subscription")
	projectId := c.GetString(urlParamProjectId)
	s, err := service.NewEventService(projectId, c.Ctx, tLogger)
	if err != nil {
		response.Error(c.Ctx, http.StatusInternalServerError, errors.NewErrorResp(errors.AgencyClientError))
		tLogger.Error("new event service when add subscription err: %+v", err)
		return
	}
	req := &model.AddSubscriptionRequest{}
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, req); err != nil {
		response.Error(c.Ctx, http.StatusBadRequest, errors.NewErrorResp(errors.RequestParseError))
		tLogger.Error("Read add subscription req body err: %+v", err)
		return
	}
	if err := validator.Validate(req); err != nil {
		response.Error(c.Ctx, http.StatusBadRequest,
			errors.NewErrorRespWithMessage(errors.RequestParamsError, err.Error()))
		tLogger.Error("The request parameter is err: %+v", err)
		return
	}
	topicUrn := c.GetString(urlParamTopicUrn)
	errC := s.AddSubscription(topicUrn, req)
	if errC != nil {
		tLogger.Error("add subscription error:%+v", errC)
		response.Error(c.Ctx, http.StatusInternalServerError, errC.ErrMsg)
		return
	}
	response.Success(c.Ctx, http.StatusAccepted, nil)
}

// 删除订阅者
func (c *EventController) CancelSubscription() {
	tLogger := logger.GetTraceLogger(c.Ctx).WithField(logger.Stage, "cancel subscription")
	projectId := c.GetString(urlParamProjectId)
	s, err := service.NewEventService(projectId, c.Ctx, tLogger)
	if err != nil {
		response.Error(c.Ctx, http.StatusInternalServerError, errors.NewErrorResp(errors.AgencyClientError))
		tLogger.Error("new event service when cancel subscription err: %+v", err)
		return
	}
	subscriptionUrn := c.GetString(urlParamSubscriptionUrn)
	errC := s.CancelSubscription(subscriptionUrn)
	if errC != nil {
		tLogger.Error("cancel subscription error:%+v", errC)
		response.Error(c.Ctx, http.StatusInternalServerError, errC.ErrMsg)
		return
	}
	response.Success(c.Ctx, http.StatusAccepted, nil)
}
